package com.lee.boot.head.first.demo.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author edz
 */
@Component
public class RedisUtils {

    @Autowired
    RedisTemplate<String, Object> redisTemplate;


    public void addValue(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * @param key
     * @param value
     * @param expireTime
     */
    public void addValueWithExpire(String key, Object value, Long expireTime) {
        redisTemplate.opsForValue().set(key, value, expireTime);
    }

    /**
     * 这种方式可以执行一段redis操作，类似调用lua脚本
     *
     * @param sessionCallback
     * @return
     */
    public Object addValueWithReturn(SessionCallback<String> sessionCallback) {
        String execute = redisTemplate.execute(sessionCallback);
        Object execute1 = new SessionCallback() {
            @Override
            public String execute(RedisOperations operations) throws DataAccessException {
                operations.opsForValue().set("", "");
                Long expire = operations.getExpire("", TimeUnit.MILLISECONDS);
                Object de = operations.opsForValue().get("de");
                return null;
            }
        }.execute(redisTemplate);

        return null;
    }

    /**
     * 事务的方式执行一段redis操作
     *
     * @param sessionCallback
     * @return
     */
    public Object addValueWithReturnTransaction(SessionCallback<String> sessionCallback) {
        String execute = redisTemplate.execute(sessionCallback);
        Object execute1 = new SessionCallback() {
            @Override
            public String execute(RedisOperations operations) throws DataAccessException {
                // 使用redis事务，
                operations.watch("key1");
                operations.multi();
                operations.opsForValue().set("", "");
                Long expire = operations.getExpire("", TimeUnit.MILLISECONDS);
                Object de = operations.opsForValue().get("de");
                // 执行事务，这时判断key1是否被修改过，如果被修改过了，那么这里面的命令都不执行，如果没有修改过则会执行，
                // 需要注意的是，在命令执行后发生报错不会回滚，
                List exec = operations.exec();
                return null;
            }
        }.execute(redisTemplate);

        return null;
    }

    /**
     * 使用批量流水线执行操作
     *
     * @param sessionCallback
     * @return
     */
    public Object addValueWithReturnPipeLine(SessionCallback<String> sessionCallback) {
        List<Object> objects = redisTemplate.executePipelined(new SessionCallback<Object>() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                for (int i = 0; i <= 100000; i++) {
                    operations.opsForValue().set("key" + i, "value" + i);
                    String value = (String) operations.opsForValue().get("key" + i);
                    if (i == 100000) {
                        System.out.println("命令只是进入队列，所以value" +
                                "为空" + value);
                        return null;
                    }
                }
                return null;
            }
        });
        return null;
    }
}
